'use client';

import toast from 'react-hot-toast';
import dayjs from 'dayjs';
import { useCallback, useMemo } from 'react';
import { useRequest, useInfiniteScroll } from 'ahooks';
import { getImageList } from 'src/actions/image';
import { getFolderListByParentId } from 'src/actions/folder';
import type { BasicTarget } from 'ahooks/lib/utils/domTarget';

type GetImageParams = Parameters<typeof getImageList>[0];
type ImageList = Awaited<ReturnType<typeof getImageList>>;

// 资源管理器：基础共享属性
export type ExplorerBaseItem = {
  id: string;
  name: string;
  createdAt: string;
  description?: string | null;
};

// 资源管理器：文件夹类型
export type ExplorerFolderItem = ExplorerBaseItem & {
  type: 'folder';
};

// 资源管理器：图片类型
export type ExplorerImageItem = ExplorerBaseItem & {
  type: 'image';
  imageUrl: string;
  fileSize: number | null;
  isPublic: boolean;
  storageSystem: string;
  tags: {
    label: string;
    value: string;
  }[];
  metadata: {
    width: number | null;
    height: number | null;
    size: number | null;
    mimeType: string | null;
    origin: Record<string, unknown> | null;
  };
};

// 资源管理器数据类型：合并类型
export type ExplorerItem = ExplorerFolderItem | ExplorerImageItem;

export interface ExplorerParams {
  /**
   * 所属文件夹目录, null表示根目录, undefined表示所有目录
   * @default null
   * @description 该数据更新将会重新加载数据(reload)
   */
  folderId?: string;
  /**
   * 搜索关键字
   */
  searchLike?: string;
  /**
   * 筛选条件
   */
  filter?: GetImageParams['filter'];
  /**
   * 排序条件
   */
  orderBy?: GetImageParams['orderBy'];
  /**
   * 无限滚动配置
   */
  infiniteScroll: {
    target: BasicTarget<Element | Document>;
    /**
     * 分页长度
     * @default 10
     */
    pageSize?: number;
    /**
     * 下拉自动加载，距离底部距离阈值
     * @default 50
     */
    threshold?: number;
  };
}

/**
 * 资源管理器无限滚动数据(folder + image)
 */
export function useExplorerInfiniteScroll(params: ExplorerParams) {
  const { folderId = null, searchLike, filter, orderBy, infiniteScroll } = params;
  const {
    target,
    pageSize: defaultPageSize = 10,
    threshold: defaultThreshold = 50,
  } = infiniteScroll;

  const isSearchMode = useMemo(() => Boolean(searchLike), [searchLike]);

  // Folder 数据
  const {
    data: folderList,
    loading: folderLoading,
    cancel: cancelFolder,
    refresh: refreshFolder,
    refreshAsync: refreshFolderAsync,
  } = useRequest(() => getFolderListByParentId(folderId), {
    refreshDeps: [folderId],
    onError(e) {
      toast.error(`文件夹数据加载失败，请稍后重试。${e.message}`);
    },
  });

  // Image 数据
  const {
    data: ImageData,
    loading: imageLoading,
    loadingMore,
    noMore,
    reload: reloadImage,
    reloadAsync: reloadImageAsync,
    cancel: cancelImage,
  } = useInfiniteScroll<ImageList>(
    (currentData) =>
      getImageList({
        searchLike,
        filter,
        folderId: isSearchMode ? undefined : folderId, // 搜索模式下查询搜索文件夹，因此传 undefined
        orderBy,
        pagination: {
          cursor: currentData?.pagination?.nextCursor ?? undefined,
          take: defaultPageSize,
        },
      }),
    {
      target,
      isNoMore: (result) => !result?.pagination?.hasMore,
      threshold: defaultThreshold, // 下拉自动加载，距离底部距离阈值
      direction: 'bottom', // 滚动方向
      reloadDeps: [folderId, searchLike, filter, orderBy],
      onError(e) {
        toast.error(`图片数据加载失败，请稍后重试。${e.message}`);
      },
    }
  );

  // Explorers 数据：合并数据
  const explorerList = useMemo<ExplorerItem[]>(() => {
    const folderListData =
      folderList?.map((folder) => ({
        type: 'folder' as const,
        id: folder.id,
        name: folder.name,
        description: folder.description,
        createdAt: dayjs(folder.createdAt).format('YYYY/MM/DD HH:mm'),
      })) ?? [];
    const imageListData =
      ImageData?.list?.map((image) => ({
        type: 'image' as const,
        id: image.id,
        name: image.fileName || '',
        description: image.alt,
        fileSize: image.fileSize,
        tags: image.tags.map((tag) => ({
          label: tag.name,
          value: tag.id,
        })),
        createdAt: dayjs(image.createdAt).format('YYYY/MM/DD HH:mm'),
        imageUrl: '/image' + image.publicUrl,
        isPublic: image.isPublic,
        storageSystem: image.storageSystem.name,
        metadata: {
          width: image.width,
          height: image.height,
          size: image.fileSize,
          mimeType: image.mimeType,
          origin: image.metadata as Record<string, unknown>,
        },
      })) ?? [];
    // 搜索模式下，文件夹数据不展示
    if (isSearchMode) {
      return imageListData;
    }
    // 非搜索模式下，合并文件夹和图片数据
    return [...folderListData, ...imageListData];
  }, [folderList, ImageData, isSearchMode]);

  const fetching = folderLoading || imageLoading;

  const cancel = useCallback(() => {
    cancelFolder();
    cancelImage();
  }, [cancelFolder, cancelImage]);

  const reload = useCallback(() => {
    reloadImage();
    refreshFolder();
  }, [reloadImage, refreshFolder]);

  const reloadAsync = useCallback(async () => {
    await Promise.all([reloadImageAsync(), refreshFolderAsync()]);
  }, [reloadImageAsync, refreshFolderAsync]);

  return {
    fetching,
    data: explorerList,
    loadingMore,
    noMore,
    reload,
    reloadAsync,
    cancel,
  };
}
